#include <iostream>
#include <unistd.h>

#include "worker.h"
#include "service.h"
#include "sunnet.h"

using namespace std;

void worker::operator()()
{
    while (true)
    {
        // 使用 this 指针或者不使用 this 指针本质上没有区别
        // 编译器会自动加上 this 指针
        // 为了增强可读性, 本项目代码统一加上 this 指针
        // cout << "I am the worker thread => " << id << endl;
        // cout << "I am the worker thread => " << this->id << endl;
        // usleep(100000); // sleep 0.1 s

        shared_ptr<service> srv = sunnet::inst->pop_global_queue();
        if (!srv)
        {
            sunnet::inst->worker_wait();
            cout << "wake up " << this->id << endl;
        }
        else
        {
            srv->process_msgs(each_num);
            this->check_and_put_into_global(srv);
        }
    }
}

void worker::check_and_put_into_global(shared_ptr<service> srv)
{
    if (srv->is_existing)
    {
        // 如果服务正在推出, 发给它的消息就再也不会回应了
        // 业务处理时, 不应该给一个正在推出的服务发送消息
        return;
    }

    // 这里为什么要加锁?
    // 此处要根据是否还有消息以判断是否将服务加入全局队列.
    // 而是否还有消息会被别的线程访问, 所以要加锁.
    pthread_spin_lock(&srv->msg_queue_lock);
    {
        // 重新放回全局队列
        if (!srv->msg_queue.empty())
        {
            sunnet::inst->push_global_queue(srv);
        }
        else
        {
            // 如果没有消息了, 设为不在全局队列中
            srv->set_in_global(false);
        }
    }
    pthread_spin_unlock(&srv->msg_queue_lock);
}